/*
* Copyright (C) 1997-2001 Id Software, Inc.
* 
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
* 
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE.
* 
* See the GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*  
*/

// Created on 01.02.2004 by RST.
// $Id: GameSVCmds.java,v 1.4 2006/01/21 21:53:32 salomo Exp $
using System;
using Defines = Suake2.UI.Defines;
using Com = Suake2.UI.qcommon.Com;
using Lib = Suake2.UI.util.Lib;
//UPGRADE_TODO: The type 'java.nio.ByteBuffer' could not be found. If it was not included in the conversion, there may be compiler issues. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1262'"
using ByteBuffer = java.nio.ByteBuffer;
namespace Suake2.UI.game
{
	
	public class GameSVCmds
	{
		
		/// <summary> 
		/// PACKET FILTERING
		/// 
		/// 
		/// You can add or remove addresses from the filter list with:
		/// 
		/// addip <ip> removeip <ip>
		/// 
		/// The ip address is specified in dot format, and any unspecified digits
		/// will match any value, so you can specify an entire class C network with
		/// "addip 192.246.40".
		/// 
		/// Removeip will only remove an address specified exactly the same way. You
		/// cannot addip a subnet, then removeip a single host.
		/// 
		/// listip Prints the current list of filters.
		/// 
		/// writeip Dumps "addip <ip>" commands to listip.cfg so it can be execed at
		/// a later date. The filter lists are not saved and restored by default,
		/// because I beleive it would cause too much confusion.
		/// 
		/// filterban <0 or 1>
		/// 
		/// If 1 (the default), then ip addresses matching the current list will be
		/// prohibited from entering the game. This is the default setting.
		/// 
		/// If 0, then only addresses matching the list will be allowed. This lets
		/// you easily set up a private game, or a game that only allows players from
		/// your local network.
		/// 
		/// </summary>
		
		public class ipfilter_t
		{
			internal int mask;
			
			internal int compare;
		}
		
		
		public static void  Svcmd_Test_f()
		{
			GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Svcmd_Test_f()\n");
		}
		
		public const int MAX_IPFILTERS = 1024;
		
		internal static GameSVCmds.ipfilter_t[] ipfilters = new GameSVCmds.ipfilter_t[MAX_IPFILTERS];
		
		internal static int numipfilters;
		
		/// <summary> StringToFilter.</summary>
		internal static bool StringToFilter(System.String s, GameSVCmds.ipfilter_t f)
		{
			
			sbyte[] b = new sbyte[]{0, 0, 0, 0};
			sbyte[] m = new sbyte[]{0, 0, 0, 0};
			
			try
			{
				SupportClass.Tokenizer tk = new SupportClass.Tokenizer(s, ". ");
				
				for (int n = 0; n < 4; n++)
				{
					b[n] = (sbyte) Lib.atoi(tk.NextToken());
					if (b[n] != 0)
						m[n] = - 1;
				}
				
				f.mask = ByteBuffer.wrap(m).getInt();
				f.compare = ByteBuffer.wrap(b).getInt();
			}
			catch (System.Exception e)
			{
				GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Bad filter address: " + s + "\n");
				return false;
			}
			
			return true;
		}
		
		/// <summary> SV_FilterPacket.</summary>
		internal static bool SV_FilterPacket(System.String from)
		{
			int i;
			int in_Renamed;
			int[] m = new int[]{0, 0, 0, 0};
			
			int p = 0;
			char c;
			
			i = 0;
			
			while (p < from.Length && i < 4)
			{
				m[i] = 0;
				
				c = from[p];
				while (c >= '0' && c <= '9')
				{
					m[i] = m[i] * 10 + (c - '0');
					c = from[p++];
				}
				if (p == from.Length || c == ':')
					break;
				
				i++;
				p++;
			}
			
			in_Renamed = (m[0] & 0xff) | ((m[1] & 0xff) << 8) | ((m[2] & 0xff) << 16) | ((m[3] & 0xff) << 24);
			
			for (i = 0; i < numipfilters; i++)
				if ((in_Renamed & ipfilters[i].mask) == ipfilters[i].compare)
				{
					//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
					return ((int) GameBase.filterban.value_Renamed) != 0;
				}
			
			return ((int) 1 - GameBase.filterban.value_Renamed) != 0;
		}
		
		/// <summary> SV_AddIP_f.</summary>
		internal static void  SVCmd_AddIP_f()
		{
			int i;
			
			if (GameBase.gi.argc() < 3)
			{
				GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Usage:  addip <ip-mask>\n");
				return ;
			}
			
			for (i = 0; i < numipfilters; i++)
				if (ipfilters[i].compare == 0xffffffff)
					break; // free spot
			if (i == numipfilters)
			{
				if (numipfilters == MAX_IPFILTERS)
				{
					GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "IP filter list is full\n");
					return ;
				}
				numipfilters++;
			}
			
			if (!StringToFilter(GameBase.gi.argv(2), ipfilters[i]))
				ipfilters[i].compare = unchecked((int) 0xffffffff);
		}
		
		/// <summary> SV_RemoveIP_f.</summary>
		internal static void  SVCmd_RemoveIP_f()
		{
			GameSVCmds.ipfilter_t f = new GameSVCmds.ipfilter_t();
			int i, j;
			
			if (GameBase.gi.argc() < 3)
			{
				GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Usage:  sv removeip <ip-mask>\n");
				return ;
			}
			
			if (!StringToFilter(GameBase.gi.argv(2), f))
				return ;
			
			for (i = 0; i < numipfilters; i++)
				if (ipfilters[i].mask == f.mask && ipfilters[i].compare == f.compare)
				{
					for (j = i + 1; j < numipfilters; j++)
						ipfilters[j - 1] = ipfilters[j];
					numipfilters--;
					GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Removed.\n");
					return ;
				}
			GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Didn't find " + GameBase.gi.argv(2) + ".\n");
		}
		
		/// <summary> SV_ListIP_f.</summary>
		internal static void  SVCmd_ListIP_f()
		{
			int i;
			sbyte[] b;
			
			GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Filter list:\n");
			for (i = 0; i < numipfilters; i++)
			{
				b = Lib.getIntBytes(ipfilters[i].compare);
				GameBase.gi.cprintf(null, Defines.PRINT_HIGH, (b[0] & 0xff) + "." + (b[1] & 0xff) + "." + (b[2] & 0xff) + "." + (b[3] & 0xff));
			}
		}
		
		/// <summary> SV_WriteIP_f.</summary>
		internal static void  SVCmd_WriteIP_f()
		{
			//UPGRADE_TODO: Class 'java.io.RandomAccessFile' was converted to 'System.IO.FileStream' which has a different behavior. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1073_javaioRandomAccessFile'"
			System.IO.FileStream f;
			//char name[MAX_OSPATH];
			System.String name;
			sbyte[] b;
			
			int i;
			cvar_t game;
			
			game = GameBase.gi.cvar("game", "", 0);
			
			if (game.string_Renamed == null)
				name = Defines.GAMEVERSION + "/listip.cfg";
			else
				name = game.string_Renamed + "/listip.cfg";
			
			GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Writing " + name + ".\n");
			
			f = Lib.fopen(name, "rw");
			if (f == null)
			{
				GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Couldn't open " + name + "\n");
				return ;
			}
			
			try
			{
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				SupportClass.RandomAccessFileSupport.WriteChars("set filterban " + (int) GameBase.filterban.value_Renamed + "\n", f);
				
				for (i = 0; i < numipfilters; i++)
				{
					b = Lib.getIntBytes(ipfilters[i].compare);
					SupportClass.RandomAccessFileSupport.WriteChars("sv addip " + (b[0] & 0xff) + "." + (b[1] & 0xff) + "." + (b[2] & 0xff) + "." + (b[3] & 0xff) + "\n", f);
				}
			}
			catch (System.IO.IOException e)
			{
				//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Throwable.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
				Com.Printf("IOError in SVCmd_WriteIP_f:" + e);
			}
			
			Lib.fclose(f);
		}
		
		/// <summary> ServerCommand
		/// 
		/// ServerCommand will be called when an "sv" command is issued. The game can
		/// issue gi.argc() / gi.argv() commands to get the rest of the parameters
		/// </summary>
		public static void  ServerCommand()
		{
			System.String cmd;
			
			cmd = GameBase.gi.argv(1);
			if (Lib.Q_stricmp(cmd, "test") == 0)
				Svcmd_Test_f();
			else if (Lib.Q_stricmp(cmd, "addip") == 0)
				SVCmd_AddIP_f();
			else if (Lib.Q_stricmp(cmd, "removeip") == 0)
				SVCmd_RemoveIP_f();
			else if (Lib.Q_stricmp(cmd, "listip") == 0)
				SVCmd_ListIP_f();
			else if (Lib.Q_stricmp(cmd, "writeip") == 0)
				SVCmd_WriteIP_f();
			else
				GameBase.gi.cprintf(null, Defines.PRINT_HIGH, "Unknown server command \"" + cmd + "\"\n");
		}
		static GameSVCmds()
		{
			{
				for (int n = 0; n < GameSVCmds.MAX_IPFILTERS; n++)
					GameSVCmds.ipfilters[n] = new ipfilter_t();
			}
		}
	}
}